#include "common_list.h"

#ifndef NULL
#define NULL ((void *)0)
#endif

void xp_slist_init(struct xp_slist_handler *handler)
{
    handler->head = NULL;
    handler->tail = NULL;
    handler->length = 0;
}

void xp_slist_add(struct xp_slist_handler *handler, struct xp_slist_node *node)
{
    node->next = handler->head;
    handler->head = node;
    if (handler->length == 0)
        handler->tail = node;
    handler->length++;
}

void xp_slist_add_tail(struct xp_slist_handler *handler, struct xp_slist_node *node)
{
    node->next = NULL;
    if (handler->length == 0)
    {
        handler->head = handler->tail = node;
    }
    else
    {
        handler->tail->next = node;
        handler->tail = node;
    }
    handler->length++;
}

void xp_slist_del(struct xp_slist_handler *handler, struct xp_slist_node *node)
{
    struct xp_slist_node *tmp = handler->head;
    if (tmp == node)
    {
        handler->head = node->next;
        handler->length--;
        return;
    }
    for (; tmp != NULL; tmp = tmp->next)
    {
        if (tmp->next == node)
        {
            tmp->next = tmp->next->next;
            handler->length--;
            return;
        }
    }
}

#if 0
/* 在表创建时必须传入已分配的内存或全局的数组 */
void xp_table_create(struct xp_table_handler *handler, struct xp_table_row *tbody, int length)
{
    handler->key_offset = -1;
    handler->rows = 0;
    handler->tsize = length-1;      // 留一个余量
    for (int i = 0; i < length; i ++) tbody[i] = {0};
    handler->tbody = tbody;
}

int xp_table_insert(struct xp_table_handler *handler, unsigned int id, void *payload)
{
    if (handler->tsize == handler->rows) return -1;     // 表格满
    for (int i = 0; i < handler->rows; i ++) {
        if (handler->tbody[i].id == id) return -2;// id需要唯一
    }
    handler->tbody[handler->rows].id = id;
    handler->tbody[handler->rows].payload = payload;
    handler->rows ++;
    return 0;
}

int xp_table_delete(struct xp_table_handler *handler, unsigned int id)
{
    char has_id = 0;
    for (int i = 0; i < handler->rows; i ++) {
        if (handler->tbody[i].id == id) {
            has_id = 1;
            handler->tbody[i] = handler->tbody[i+1];
            handler->tbody[i+1].id = id;
        }
    }
    if (has_id) {
        handler->rows --;
        return 0;
    }

    return -1;  // not in table
}

int xp_table_select(struct xp_table_handler *handler, unsigned int id, void **payload)
{
    for (int i = 0; i < handler->rows; i ++) {
        if (handler->tbody[i].id == id) {
            *payload = handler->tbody[i]->payload;
            return 0;
        }
    }
    return -1;  // not found
}

int xp_table_update(struct xp_table_handler *handler, unsigned int id, void *payload)
{
    for (int i = 0; i < handler->rows; i ++) {
        if (handler->tbody[i].id == id) {
            handler->tbody[i].payload = payload;
            return 0;
        }
    }
    return -1;  // not in table
}

int xp_table_sortby_index(struct xp_table_handler *handler)
{
    return 0;
}

int xp_table_sortby_index_desc(struct xp_table_handler *handler)
{
    return 0;
}

void xp_table_create_with_key(struct xp_table_handler *handler, struct xp_table_row *tbody, int length, int key_offset)
{
    handler->key_offset = key_offset;
    handler->rows = 0;
    handler->tsize = length-1;      // 留一个余量
    for (int i = 0; i < length; i ++) tbody[i] = {0};
    handler->tbody = tbody;
}

int xp_table_insert_by_key(struct xp_table_handler *handler, unsigned int id, void *payload)
{
    unsigned char *key = (unsigned char *)((unsigned int)payload + handler->key_offset);
    if (handler->tsize == handler->rows) return -1;     // 表格满
    for (int i = 0; i < handler->rows; i ++) {
        if ( 0 == strcmp(handler->tbody[i].key, key) ||\
            id == handler->tbody[i].id) return -2;      // key需要唯一
    }
    handler->tbody[handler->rows].key = id;
    handler->tbody[handler->rows].key = key;
    handler->tbody[handler->rows].payload = payload;
    handler->rows ++;
    return 0;
}

int xp_table_delete_by_key(struct xp_table_handler *handler, unsigned char *key)
{
    char has_key = 0;
    for (int i = 0; i < handler->rows; i ++) {
        if (0 == strcmp(handler->tbody[i].key, key)) {
            has_key = 1;
            handler->tbody[i] = handler->tbody[i+1];
            handler->tbody[i+1].key = key;
        }
    }
    if (has_key) {
        handler->rows --;
        return 0;
    }

    return -1;  // not in table
}

int xp_table_select_by_key(struct xp_table_handler *handler, unsigned char *key, void **payload)
{
    for (int i = 0; i < handler->rows; i ++) {
        if (strcmp(handler->tbody[i].key, key)) {
            *payload = handler->tbody[i]->payload;
            return 0;
        }
    }
    return -1;  // not found
}

int xp_table_update_by_key(struct xp_table_handler *handler, unsigned char *key, void *payload)
{
    unsigned char *newKey = (unsigned char *)((unsigned int)payload + handler->key_offset);
    for (int i = 0; i < handler->rows; i ++) {
        if (0 == strcmp(handler->tbody[i].key, key)) {
            handler->tbody[i].payload = payload;
            strcpy(newKey, key);
            return 0;
        }
    }
    return -1;  // not in table
}

#endif
